﻿//===========================[ 8 / 2 / 2011 LVI ]=============================
//				Copyright c Vitaly Lyaschenko <SkyChameleon@gmail.com>
//								Source file
// Purpose: 
//=============================================================================
#include "cFileManager.h"
#include "cwLogger.h"

// внешней экземпляр
std::vector<std::string> cFileManager::pathStackFile;

///////////////////////////////////////////////////////////////////////////
// http://www.rsdn.ru/forum/cpp/2728160.flat.aspx
// http://www.dinkumware.com/manuals/?manual=compleat&page=multibyte.html
// string to wstring
std::wstring to_wstring( const std::string& in, std::locale loc )
{
	std::wstring out( in.length(), 0 );
	std::string::const_iterator it_beg = in.begin(), it_end = in.end();
	std::wstring::iterator j = out.begin();

	for( ; it_beg != it_end; ++it_beg, ++j )
		*j = std::use_facet< std::ctype< wchar_t > > ( loc ).widen( *it_beg );

	return out;
}
// TODO : / modify !
// wstring to string
std::string to_string( const std::wstring& in, std::locale loc )
{
	std::string out( in.length(), 0 );
	std::wstring::const_iterator it_beg = in.begin(), it_end = in.end();
	std::string::iterator j = out.begin();

	for( ; it_beg != it_end; ++it_beg, ++j )
		*j = std::use_facet< std::ctype< char > > ( loc ).narrow( *it_beg );

	return out;
}
///////////////////////////////////////////////////////////////////////////
// http://www.cplusplus.com/reference/clibrary/cstdlib/mbtowc/
// http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/rtref/mbtowc.htm
// http://stackoverflow.com/questions/4357267/mbstowcs-s-is-causing-my-program-to-crash
// преобразует символ в расширенный символ
wchar_t* to_wchar( const char *in_ch, std::locale loc )
{
	int  size = strlen( in_ch ) + 1;

	size_t length = 0;
	wchar_t *str_w = new wchar_t[ size ];
	//mbstowcs( str_w, in_ch, 7 );
	mbstowcs_s( &length, str_w, size, in_ch, size );
	return str_w;
}

cFileManager::cFileManager()
{
	pathStackFile.push_back("patch");
	cwLogger::writeINFO("< File Manager > Instance Create.");
}

cFileManager::~cFileManager()
{
	pathStackFile.clear();
	cwLogger::writeINFO("< File Manager > Instance Destroy.");
}

///////////////////////////////////////////////////////////////////////////
// регистрация путей к файлам
void cFileManager::regiserPath( const std::string &path )
{
	if (path.empty())
	{// если передана пустая строка
		cwLogger::writeERROR( "Failed to register path -> NULL" );
		return;
	}

	// для всего "стека" путей к файлам ищем совпадения,
	// если путь к файлу существует -> выходим,
	for ( size_t i = 0; i < pathStackFile.size(); i++ )
		if (pathStackFile[i] == path)
			return;
	// добавляем в "стек".
	pathStackFile.push_back( path );
	cwLogger::writeINFO( "Registering data path -> "+std::string( path ) );
}

///////////////////////////////////////////////////////////////////////////
// ищет в зарегестрированных путях подходящий путь к файлу
std::string cFileManager::lookUpPath( const std::string &path )
{
	if (path.empty())
		return std::string( "Empty_path_to_LookUp" );

	std::ifstream testToOpenFile;
	std::string buffer;

	testToOpenFile.open(path);
	// если файл сразу открылся, то ничего искать ненадо
	if ( testToOpenFile.is_open() )
	{
		testToOpenFile.close();
		return path;
	}

	size_t cout = pathStackFile.size();
	// соеденяя имя файла со всеми зарегестрированными путями
	// проверяем его на открытие, если открылся,
	// возвращаем корректный путь к нему
	for ( size_t i = 0; i < cout; i++ )
	{
		buffer  = pathStackFile[i];
		buffer += path;

		testToOpenFile.open( buffer.data() );

		if ( testToOpenFile.is_open() )
		{
			testToOpenFile.close();
			return buffer;
		}
	}
	cwLogger::writeINFO( "File : " + std::string(path) + "NOT FOUND!" );

	return std::string( "NOT FOUND" );
}

///////////////////////////////////////////////////////////////////////////
// возвращает указатель на буфер прочитанных данных всего файла 
void * cFileManager::getFileData( const std::string &fileName, const typeFile type )
{
	char *data;
	cFile file( fileName, type, fRead );
	size_t size;

	if (file.getStateOK())
	{
		size = file.getSize();
		data = new char[ size + 1 ];
		file.seekTo( 0 );
		file.readFile( data, size );
		data[ size ] = '\0';
		return data;
	}
	return "ERROR_get_file";
}

///////////////////////////////////////////////////////////////////////////
// write to file
void cFileManager::writeFile( const std::string &fileName, char *data, size_t size, const typeFile type )
{
	cFile file( fileName, type, fWrite );
	if ( file.getStateOK() )
		file.writeToFile( data, size );
}

///////////////////////////////////////////////////////////////////////////
// создание файла. В случае совпадения имени файл будет перезаписан
void cFileManager::rewriteFile( const std::string &fileName, char *data, size_t size, const typeFile type )
{
	cFile file( fileName, type, fReWrite );
	if ( file.getStateOK() )
		file.writeToFile( data, size );
}

///////////////////////////////////////////////////////////////////////////
// возвращает расширение файла
std::string cFileManager::extractFileExtension( const std::string &fileName )
{
	if ( fileName.empty() ) 
		return "Empty_path";

	int i = fileName.size() - 1;
	std::string buf;
	while( ( fileName[i] != '.' ) && (i > 0) )
		buf = fileName[i--] + buf;

	return buf;
}

///////////////////////////////////////////////////////////////////////////
// возвращает имя файла без расширения
std::string cFileManager::extractFileName( const std::string &fileName )
{
	if ( fileName.empty() ) 
		return "Empty_path";

	int i = fileName.size() - 1;
	std::string buf;
	while( i > 0 )
	{
		if( fileName[i--] == '.' )
		{
			while ( i >= 0 )
			{
				if ( fileName[i] == '/' )
					break;
				
				buf = fileName[i--] + buf;
			}
			break;
		}
	}
	return buf;
}

///////////////////////////////////////////////////////////////////////////
// возвращает имя файла с расширением
std::string cFileManager::extractFileNameEx( const std::string &fileName )
{
	if ( fileName.empty() ) 
		return "Empty_path";

	int i = fileName.size() - 1;

	std::string buf;

	while( i > 0 )
	{
		if ( (fileName[i] == '/') )
			break;

		buf = fileName[i--] + buf;
	}

	return buf;
}

///////////////////////////////////////////////////////////////////////////
// прочитать файл в строку
std::string cFileManager::getFileAsString( const std::string &fileName )
{
	cFile file;
	std::string strBuff;
	file.open_file(fileName, fText, fRead );
	if ( file.getStateOK() )
	{
		//узнаем размер файла, и выделяем память в строке
		strBuff.resize( file.getSize() );
		//копируем данные
		file.readFile( (void*)strBuff.data(), strBuff.size());
		//file.release();
		return strBuff;
	}
	return "ERROR_get_file";
}